package com.zx.validation.test;

import com.zx.core.exception.ParameterException;
import com.zx.validation.annotation.ParameterValidation;
import com.zx.validation.annotation.ParameterValidations;
import com.zx.validation.enums.ValidateRulesEnum;
import com.zx.validation.groups.Create;
import com.zx.validation.groups.Query;
import com.zx.validation.groups.Update;
import lombok.Data;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import static org.junit.jupiter.api.Assertions.assertThrows;

/**
 * 业务场景分组验证示例
 * <p>
 * 演示如何在实际业务场景中使用分组验证功能
 *
 * @author zhou xun
 * @since 2024-11-13
 */
@SpringBootTest(classes = BusinessGroupValidationExample.TestConfig.class)
@ComponentScan(basePackages = "com.zx.validation")
@EnableAspectJAutoProxy
public class BusinessGroupValidationExample {

    @Autowired
    private UserController userController;

    /**
     * 测试创建用户功能
     */
    @Test
    public void testCreateUser() {
        UserParam userParam = new UserParam();
        userParam.setName("testUser");
        userParam.setEmail("test@example.com");
        userParam.setPhone("12345678901");
        userParam.setAge(25); // 设置age字段以避免验证失败

        // 这应该通过验证
        userController.createUser(userParam);
    }

    /**
     * 测试更新用户功能
     */
    @Test
    public void testUpdateUser() {
        UserParam userParam = new UserParam();
        userParam.setId("12345");
        userParam.setName("updatedUser");
        userParam.setPhone("12345678901");
        userParam.setAge(25); // 设置age字段以避免验证失败

        // 这应该通过验证
        userController.updateUser(userParam);
    }

    /**
     * 测试查询用户功能
     */
    @Test
    public void testQueryUser() {
        UserQueryParam queryParam = new UserQueryParam();
        queryParam.setName("testUser");
        queryParam.setEmail("test@example.com");
        queryParam.setMinAge(18);
        queryParam.setMaxAge(65);

        // 这应该通过验证
        userController.queryUser(queryParam);
    }

    /**
     * 测试查询用户功能 - 只设置部分字段应该失败
     */
    @Test
    public void testQueryUserWithPartialFields() {
        UserQueryParam queryParam = new UserQueryParam();
        queryParam.setName("testUser");
        // 不设置其他字段，应该触发验证失败，因为LENGTH规则要求非null值

        // 这应该抛出验证异常
        assertThrows(Exception.class, () -> userController.queryUser(queryParam));
    }

    /**
     * 测试查询用户功能 - 显式设置null值应该失败
     */
    @Test
    public void testQueryUserWithNullFields() {
        UserQueryParam queryParam = new UserQueryParam();
        queryParam.setName("testUser");
        queryParam.setEmail(null);  // 显式设置为null
        queryParam.setMinAge(null);
        queryParam.setMaxAge(null);

        // 这应该抛出验证异常
        assertThrows(Exception.class, () -> userController.queryUser(queryParam));
    }

    /**
     * 测试查询用户功能 - 设置所有字段应该通过
     */
    @Test
    public void testQueryUserWithAllFields() {
        UserQueryParam queryParam = new UserQueryParam();
        queryParam.setName("testUser");
        queryParam.setEmail("test@example.com");
        queryParam.setMinAge(18);
        queryParam.setMaxAge(65);

        // 这应该通过验证
        userController.queryUser(queryParam);
    }

    /**
     * 测试查询用户失败的情况 - 字段验证失败
     */
    @Test
    public void testQueryUserValidationFailure() {
        UserQueryParam queryParam = new UserQueryParam();
        queryParam.setName("a".repeat(51)); // 长度超过50，应该触发验证失败
        queryParam.setEmail("test@example.com");
        queryParam.setMinAge(18);
        queryParam.setMaxAge(65);

        // 这应该抛出验证异常
        assertThrows(Exception.class, () -> userController.queryUser(queryParam));
    }

    /**
     * 测试无匹配字段的情况
     */
    @Test
    public void testNoMatchingFields() {
        UserQueryParam queryParam = new UserQueryParam();
        queryParam.setName("testUser");

        // 这应该抛出ParameterException异常，因为UserQueryParam没有任何字段属于Create分组
        assertThrows(ParameterException.class, () -> userController.demonstrateNoMatchingFields(queryParam));
    }

    /**
     * 测试创建用户失败的情况 - 缺少必需字段
     */
    @Test
    public void testCreateUserValidationFailure() {
        UserParam userParam = new UserParam();
        userParam.setName("testUser");
        // 缺少email字段，应该触发验证失败
        userParam.setEmail(null);  // 显式设置为null

        // 这应该抛出验证异常
        assertThrows(Exception.class, () -> userController.createUser(userParam));
    }

    /**
     * 测试更新用户失败的情况 - 缺少必需字段
     */
    @Test
    public void testUpdateUserValidationFailure() {
        UserParam userParam = new UserParam();
        // userParam.setId("12345"); // 缺少ID字段，应该触发验证失败
        userParam.setId(null); // 显式设置为null
        userParam.setName("updatedUser");

        // 这应该抛出验证异常
        assertThrows(Exception.class, () -> userController.updateUser(userParam));
    }

    // 测试配置类
    @org.springframework.context.annotation.Configuration
    @ComponentScan(basePackages = "com.zx.validation")
    @EnableAspectJAutoProxy
    public static class TestConfig {
        // 空的配置类，用于启动Spring上下文
    }

    /**
     * 用户管理控制器示例
     */
    @Component
    public static class UserController {
        /**
         * 创建用户
         * 使用Create分组验证
         */
        @ParameterValidations(
                value = {
                        @ParameterValidation(
                                index = 0,
                                desc = "用户参数",
                                rules = {ValidateRulesEnum.OBJECT},
                                groups = {Create.class}
                        )
                }
        )
        public void createUser(UserParam userParam) {
            // 实际业务逻辑
            System.out.println("创建用户: " + userParam.name);
        }

        /**
         * 更新用户
         * 使用Update分组验证
         */
        @ParameterValidations(
                value = {
                        @ParameterValidation(
                                index = 0,
                                desc = "用户参数",
                                rules = {ValidateRulesEnum.OBJECT},
                                groups = {Update.class}
                        )
                }
        )
        public void updateUser(UserParam userParam) {
            // 实际业务逻辑
            System.out.println("更新用户: " + userParam.name);
        }

        /**
         * 查询用户
         * 使用Query分组验证
         */
        @ParameterValidations(
                value = {
                        @ParameterValidation(
                                index = 0,
                                desc = "用户查询参数",
                                rules = {ValidateRulesEnum.OBJECT},
                                groups = {Query.class}
                        )
                }
        )
        public void queryUser(UserQueryParam queryParam) {
            // 实际业务逻辑
            System.out.println("查询用户: " + queryParam.name);
        }

        /**
         * 演示分组不匹配的情况
         * 当使用Query分组时，只验证查询相关的字段
         */
        @ParameterValidations(
                value = {
                        @ParameterValidation(
                                index = 0,
                                desc = "用户参数",
                                rules = {ValidateRulesEnum.OBJECT},
                                groups = {Query.class}
                        )
                }
        )
        public void demonstrateGroupMismatch(UserParam userParam) {
            // 实际业务逻辑
            System.out.println("演示分组不匹配: " + userParam.name);
            System.out.println("在Query分组下，UserParam中的email字段（属于Create分组）不会被验证");
        }

        /**
         * 演示没有任何字段匹配指定分组的情况
         */
        @ParameterValidations(
                value = {
                        @ParameterValidation(
                                index = 0,
                                desc = "无匹配字段的对象",
                                rules = {ValidateRulesEnum.OBJECT},
                                groups = {Create.class}
                        )
                }
        )
        public void demonstrateNoMatchingFields(UserQueryParam queryParam) {
            // 实际业务逻辑
            System.out.println("演示无匹配字段: " + queryParam.name);
        }
    }

    /**
     * 用户参数类
     * 演示不同字段在不同业务场景下的验证规则
     */
    @Data
    public static class UserParam {
        /**
         * 用户ID
         * 在更新操作中是必需的
         */
        @ParameterValidation(
                index = 0,
                desc = "用户ID",
                rules = {ValidateRulesEnum.NOT_NULL},
                groups = {Update.class}
        )
        private String id;

        /**
         * 用户名
         * 在创建和更新操作中是必需的
         */
        @ParameterValidation(
                index = 0,
                desc = "用户名",
                rules = {ValidateRulesEnum.NOT_NULL, ValidateRulesEnum.LENGTH},
                length = "1~50",
                groups = {Create.class, Update.class}
        )
        private String name;

        /**
         * 邮箱
         * 在创建操作中是必需的
         */
        @ParameterValidation(
                index = 0,
                desc = "邮箱",
                rules = {ValidateRulesEnum.NOT_NULL, ValidateRulesEnum.LENGTH},
                length = "1~100",
                groups = {Create.class}
        )
        private String email;

        /**
         * 手机号
         * 在创建和更新操作中都是可选的
         */
        @ParameterValidation(
                index = 0,
                desc = "手机号",
                rules = {ValidateRulesEnum.LENGTH},
                length = "11",
                groups = {Create.class, Update.class}
        )
        private String phone;

        /**
         * 年龄
         * 在所有操作中都是可选的
         */
        @ParameterValidation(
                index = 0,
                desc = "年龄",
                rules = {ValidateRulesEnum.NUMBER_MIN, ValidateRulesEnum.NUMBER_MAX},
                numberMin = 0,
                numberMax = 200
        )
        private Integer age;
    }

    /**
     * 用户查询参数类
     * 演示查询场景下的验证规则
     */
    @Data
    public static class UserQueryParam {
        /**
         * 用户名（模糊查询）
         * 在查询操作中是可选的
         */
        @ParameterValidation(
                index = 0,
                desc = "用户名",
                rules = {ValidateRulesEnum.LENGTH},
                length = "1~50",
                groups = {Query.class}
        )
        private String name;

        /**
         * 邮箱（精确查询）
         * 在查询操作中是可选的
         */
        @ParameterValidation(
                index = 0,
                desc = "邮箱",
                rules = {ValidateRulesEnum.LENGTH},
                length = "1~100",
                groups = {Query.class}
        )
        private String email;

        /**
         * 最小年龄
         * 在查询操作中是可选的
         */
        @ParameterValidation(
                index = 0,
                desc = "最小年龄",
                rules = {ValidateRulesEnum.NUMBER_MIN, ValidateRulesEnum.NUMBER_MAX},
                numberMin = 0,
                numberMax = 200,
                groups = {Query.class}
        )
        private Integer minAge;

        /**
         * 最大年龄
         * 在查询操作中是可选的
         */
        @ParameterValidation(
                index = 0,
                desc = "最大年龄",
                rules = {ValidateRulesEnum.NUMBER_MIN, ValidateRulesEnum.NUMBER_MAX},
                numberMin = 0,
                numberMax = 200,
                groups = {Query.class}
        )
        private Integer maxAge;
    }
}